package com.example.byexample

fun main() {
    // 以函数为参数
    val sumResult = calculate(4, 5, ::sum) // ::是在Kotlin中按名称引用函数的表示法。
    val mulResult = calculate(4, 5) { a, b -> a * b }
    println("sumResult $sumResult, mulResult $mulResult")

    // 返回函数
    val func = operation()
    println(func(2))

    // Lambda 函数
    // Lambda 函数（“lambdas”）是一种创建临时函数的简单方法。
    val upperCase1: (String) -> String = { str: String -> str.uppercase() }
    val upperCase2: (String) -> String = { str -> str.uppercase() }
    val upperCase3 = { str: String -> str.uppercase() }
    // val upperCase4 = { str -> str.uppercase() }
    val upperCase5: (String) -> String = { it.uppercase() }
    val upperCase6: (String) -> String = String::uppercase // 如果您的 lambda 由单个函数调用组成，您可以使用函数指针 (::) 。

    println(upperCase1("hello"))
    println(upperCase2("hello"))
    println(upperCase3("hello"))
    println(upperCase5("hello"))
    println(upperCase6("hello"))

    // 扩展函数和属性
    // TODO: 扩展的思想我知道，但是这写法没看懂
    val order = Order(listOf(Item("Bread", 25.0F), Item("Wine", 29.0F), Item("Water", 12.0F)))
    println("Max priced item name: ${order.maxPricedItemName()}")
    println("Max priced item value: ${order.maxPricedItemValue()}")
    println("Items: ${order.commaDelimitedItemNames}")

}

data class Item(val name: String, val price: Float)

data class Order(val items: Collection<Item>)

fun Order.maxPricedItemValue(): Float = this.items.maxByOrNull { it.price }?.price ?: 0F // 为Order类型添加扩展函数。
fun Order.maxPricedItemName() = this.items.maxByOrNull { it.price }?.name ?: "NO_PRODUCTS"

val Order.commaDelimitedItemNames: String get() = items.joinToString { it.name } // 为Order类型添加扩展属性。

fun <T> T?.nullSafeToString() = this?.toString() ?: "NULL" // 对空引用执行扩展。

fun operation(): (Int) -> Int {
    return ::square
}

fun square(x: Int) = x * x

fun sum(x: Int, y: Int) = x + y

fun calculate(x: Int, y: Int, operation: (Int, Int) -> Int): Int {
    return operation(x, y)
}
